package com.wmd.core.swagger;

import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.Optional;
import com.wmd.core.annotation.ApiJsonEntity;
import com.wmd.core.annotation.ApiJsonObject;
import com.wmd.core.annotation.ApiJsonObjects;
import com.wmd.core.annotation.ApiJsonProperty;
import io.swagger.annotations.ApiModelProperty;
import javassist.*;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.BooleanMemberValue;
import javassist.bytecode.annotation.StringMemberValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ResolvedMethodParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.ParameterBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.spi.service.contexts.ParameterContext;
import springfox.documentation.swagger.common.SwaggerPluginSupport;

import java.lang.reflect.Field;
import java.util.*;

/**
 * Simple to Introduction
 *
 * @projectName:sms
 * @packageName:lyc.example.sms.swagger
 * @className:MapReaderForApi
 * @Description:[解析自定义Map描述]
 * @Author:luyincheng
 * @CreateDate:2021/1/18 14:20
 * @blog:[方法具体上行/下行参数文档]
 */
@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 3) // plugin加载顺序，默认是最后加载
@Profile({"dev","test"})
public class MapReaderForApi implements ParameterBuilderPlugin {


    @Autowired
    private TypeResolver typeResolver;

    private final static String basePackage = "com.wmd.core.entity.extra."; // 动态生成的虚拟DTO Class的包路径

    @Override
    public void apply(ParameterContext parameterContext) {

        ResolvedMethodParameter methodParameter = parameterContext.resolvedMethodParameter();
        OperationContext operationContext = parameterContext.getOperationContext();
        String apiUrl = operationContext.requestMappingPattern();

        System.out.println(apiUrl);
//下行代码导致同时存在Map和String参数导致String不生效被覆盖
//        if (methodParameter.getParameterType().canCreateSubtype(Map.class) || methodParameter.getParameterType().canCreateSubtype(String.class)) { // 判断是否需要修改对象ModelRef,这里我判断的是Map类型和String类型需要重新修改ModelRef对象
        if (methodParameter.getParameterType().canCreateSubtype(Map.class) || (methodParameter.getParameterType().canCreateSubtype(String.class) && methodParameter.findAnnotation(RequestBody.class).isPresent())) { // 判断是否需要修改对象ModelRef,这里我判断的是Map类型和String类型需要重新修改ModelRef对象
            // Optional<ApiJsonObject> optional = methodParameter.findAnnotation(ApiJsonObject.class); // 根据参数上的ApiJsonObject注解中的参数动态生成Class,该方式获取不到方法注解

            Optional<ApiJsonObject> optional = operationContext.findAnnotation(ApiJsonObject.class); // 根据参数上的ApiJsonObject注解中的参数动态生成Class

            Optional<ApiJsonObjects> optionals = operationContext.findAnnotation(ApiJsonObjects.class);

            List<ApiJsonObject> apiJsonObjects = new ArrayList<>();
            if (optional.isPresent()) {
                apiJsonObjects.add(optional.get());
            }
            if (optionals.isPresent()) {
                for (ApiJsonObject a : optionals.get().value()) {
                    if (apiJsonObjects.size() >= 2) {//忽略多余注释
                        break;
                    }
                    apiJsonObjects.add(a);
                }
            }
            //System.out.println("a numbers:"+optionals.get().value().length);
            if (apiJsonObjects.size() > 0) {//如果有注释
                Set<Integer> ParamterOrResponseSet = new HashSet<>();
                for (ApiJsonObject apiJsonObject : apiJsonObjects) {

                    System.out.println(apiJsonObject.toString());

                    if (ParamterOrResponseSet.contains(2)) {//2为已经设置参数和返回值，后边都不处理
                        break;
                    }
                    if (ParamterOrResponseSet.contains(apiJsonObject.ParamterOrResponse())) {//避免重复类型
                        continue;
                    }
                    ParamterOrResponseSet.add(apiJsonObject.ParamterOrResponse());
                    String name = null;
                    name = apiJsonObject.name() + "_" + operationContext.getName() + "_" + apiJsonObject.ParamterOrResponse(); // model 名称

                   /* ApiJsonProperty[] properties =apiJsonObject.properties();
                    ApiJsonEntity[] entities = apiJsonObject.entities();


                    Class c = createRefModel(properties, entities, name,apiJsonObject.description());
                    ResolvedType type = typeResolver.resolve(c);
                    DocumentationContext documentationContext = operationContext.getDocumentationContext();
                    Set<ResolvedType> resolvedTypes = documentationContext.getAdditionalModels();
                    resolvedTypes.add(type); // 向documentContext的Models中添加我们新生成的Class*/
                    ModelRef modelRef = new ModelRef(name);


                    if (apiJsonObject.ParamterOrResponse() == 0 || apiJsonObject.ParamterOrResponse() == 2) {//参数类型或者全部
                        parameterContext
                                .parameterBuilder() // 修改Map参数的ModelRef为我们动态生成的class
                                .parameterType("body")
                                .modelRef(modelRef)
                                .name(name)
                                .description("JSON示例");
                    }
                }
            }
        }

    }

    @Override
    public boolean supports(DocumentationType delimiter) {
        return true;
    }
}
